#include "ec11.h"


ButtonState button_state = IDLE;
uint32_t last_press_time = 0;
int click_count = 0;
bool held_triggered = false;

bool timer_active = false;  // 定时器是否激活
pthread_t click_timer_thread;  // 定时器线程句柄
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 互斥锁


// 长按超时处理
pthread_t long_press_thread;
bool is_long_pressing = false;
double long_press_start_time = 0;
bool long_press_handled = false;
double long_press_timeout = LONG_PRESS_DELAY;  


Pi_Renc_t * renc;

void callback(int way)
{
   static int pos = 0;
   pos += way;
   printf("pos=%d\n", pos);
}

// 长按检测线程
void* check_long_press(void* arg) {
    double startTime = get_current_time();
    while (1) {
        pthread_mutex_lock(&mutex);
        if (is_long_pressing && !long_press_handled) {
            double elapsed = get_current_time() - long_press_start_time;
            if (elapsed >= long_press_timeout) { // 超过3秒
                printf("============== 长按超过2秒，自动执行操作\n");
                long_press_handled = true; // 只执行一次
                held_triggered = true;
                button_state = LONG_PRESSED;
            }
        }
        pthread_mutex_unlock(&mutex);
        usleep(10000); // 每10ms检查一次
    }
    return NULL;
}

// 单击回调处理函数
void handle_single_click() {
    pthread_mutex_lock(&mutex);
    // 如果当前点击计数还是1，并且没有触发长按，则说明是单击事件
    if (click_count == 1 && !held_triggered) {
        printf("============== 单击触发%.6f 秒\n", get_current_time());
        // 单击触发后，恢复中间变量的值
        button_state = CLICKED;  // 单击
        click_count = 0;
        is_long_pressing = false;  // 单击触发了，长按就不要监听了
    }
    timer_active = false;
    pthread_mutex_unlock(&mutex);
}

// 定时器线程函数
void* click_timer(void* arg) {
    printf("单击计时开始-------------------------------%.6f 秒\n", get_current_time());
    usleep(CLICK_DELAY * 1000); // 延迟 CLICK_DELAY ms
    handle_single_click();
    return NULL;
}

static uint32_t last_interrupt_time = 0;
// 按键按下回调函数
void buttonPressed(int gpio, int level, uint32_t tick) {
    // 消抖：两次中断间隔小于 200ms 则忽略
    uint32_t current_time = tick;
    if (current_time - last_interrupt_time < 200) {
        return;
    }
    last_interrupt_time = current_time;
    
    static double press_start_time = 0;
    if (level == 0) { // 按钮按下
        press_start_time = get_current_time();
        printf("按钮按下-------------------------------%.6f 秒\n", press_start_time);
        button_state = PRESSED;
        held_triggered = false;

        // 启动长按超时检测
        pthread_mutex_lock(&mutex);
        is_long_pressing = true;
        long_press_start_time = press_start_time;
        long_press_handled = false;
        pthread_mutex_unlock(&mutex);
    } else { // 按钮释放
        printf("按钮释放-------------------------------%.6f 秒\n", get_current_time());
        if (button_state == PRESSED) {
            double press_duration = get_current_time() - press_start_time;
            // printf("释放时减去按下时：%.6f 秒\n", press_duration);
            if (held_triggered) {  // 长按已触发,还没处理过
                printf("当前为长按，直接退出-------------------------------%.6f 秒\n", get_current_time());
                held_triggered = false;
                pthread_mutex_lock(&mutex);
                is_long_pressing = false; // 停止检测
                pthread_mutex_unlock(&mutex);
                return;
            }
            if (press_duration < LONG_PRESS_DELAY) {
               if (click_count == 0) {  // 第一次点击
                    // 还不能判断为单击，还需要启动个计时，过多少时间后没有继续按下才为单击
                    timer_active = true;
                    pthread_create(&click_timer_thread, NULL, click_timer, NULL);
                    click_count = 1;
                    printf("点击次数-------------------------------click_count=%d \n", click_count);
               } else if (click_count == 1) {  // 第二次点击
                    if (timer_active) {
                        timer_active = false;
                        pthread_cancel(click_timer_thread);
                    }
                    click_count = 0;
                    button_state = DOUBLE_CLICKED;
                    printf("============== 双击触发\n");
                    is_long_pressing = false;  // 检测到双击触发了，就把长按检测取消
               }
            } else {
                printf("============== 长按触发\n");
                button_state = LONG_PRESSED;
                pthread_mutex_lock(&mutex);
                is_long_pressing = false; // 停止检测
                click_count = 0;  //重置点击计数
                pthread_mutex_unlock(&mutex);
                if (timer_active) {
                    timer_active = false;
                    pthread_cancel(click_timer_thread);
                }
                held_triggered = true; // 标记已触发长按
            }
        }
    }
}

int EC11_Init(void) {
    // 初始化 pigpio 库
    if (gpioInitialise() < 0) {
        fprintf(stderr, "pigpio 初始化失败\n");
        return 1;
    }
    renc = Pi_Renc(TRIM_A, TRIM_B, callback);  // 使用 BCM4 和 BCM17
    if (renc == NULL) {
        fprintf(stderr, "编码器初始化失败\n");
        return 1;
    }

    // 启动长按检测线程
    pthread_create(&long_press_thread, NULL, check_long_press, NULL);
    // 设置引脚为输入模式
    gpioSetMode(BUTTON_PIN, PI_INPUT);
    // 设置上拉电阻（内部上拉）
    gpioSetPullUpDown(BUTTON_PIN, PI_PUD_UP);
    // 注册中断回调：下降沿和上升沿都触发
    gpioSetAlertFunc(BUTTON_PIN, buttonPressed);
    printf("正在监听按钮状态。按 Ctrl+C 停止。\n");
    return 0;
}

ButtonState Get_EC11_State(void)
{ 
    return button_state;
}

void Reset_EC11_State(void)
{ 
    button_state = IDLE;
}



static void _cb(int gpio, int level, uint32_t tick, void *user)
{
   Pi_Renc_t *renc;

   renc = user;

   if (gpio == renc->gpioA) renc->levA = level; else renc->levB = level;

   if (gpio != renc->lastGpio) /* debounce */
   {
      renc->lastGpio = gpio;

      if ((gpio == renc->gpioA) && (level == 1))
      {
         if (renc->levB) 
         {
            (renc->callback)(1);
            renc->status = 1; // 正转
            button_state = UP;
         }
      }
      else if ((gpio == renc->gpioB) && (level == 1))
      {
         if (renc->levA) 
         {
            (renc->callback)(-1);
            renc->status = -1; // 反转
            button_state = DOWN;
         }
      }
   }
}

Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback)
{
   Pi_Renc_t *renc;

   renc = malloc(sizeof(Pi_Renc_t));

   if (renc == NULL) return NULL;

   renc->gpioA = gpioA;
   renc->gpioB = gpioB;
   renc->gpioBtn = -1;     // 默认不启用按钮
   renc->callback = callback;
   renc->levA=0;
   renc->levB=0;
   renc->lastGpio = -1;
   renc->btnLastLevel = 1;
   renc->clickCount = 0;

   gpioSetMode(gpioA, PI_INPUT);
   gpioSetMode(gpioB, PI_INPUT);

   gpioSetPullUpDown(gpioA, PI_PUD_UP);
   gpioSetPullUpDown(gpioB, PI_PUD_UP);

   gpioSetAlertFuncEx(gpioA, _cb, renc);
   gpioSetAlertFuncEx(gpioB, _cb, renc);

   return renc;
}

void Pi_Renc_cancel(Pi_Renc_t *renc)
{
   if (renc)
   {
      gpioSetAlertFunc(renc->gpioA, 0);
      gpioSetAlertFunc(renc->gpioB, 0);

      free(renc);
   }
}

void Deinit_EC11(void)
{
   Pi_Renc_cancel(renc);
   gpioTerminate();
}
